home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 May: Tool Chest / Developer CD Series May 1996 (Tool Chest) (Apple Computer) (1996).iso / Sample Code / SCSI Samples 1.0 / SCSI Driver Example 06⁄07 ƒ / disk.a < prev    next >
Encoding:
Text File  |  1994-06-16  |  14.5 KB  |  444 lines  |  [TEXT/MPS ]

  1. ;____________________________________________________________________________________
  2. ;
  3. ;    File:        disk.a
  4. ;
  5. ;    Contains:    The assembly driver header and some misc other stuff
  6. ;                Part of the Example SCSI Driver
  7. ;
  8. ;    Copyright:    © 1993-94 by Apple Computer, Inc., all rights reserved.
  9. ;
  10. ;____________________________________________________________________________________
  11.  
  12.  
  13.  
  14.             BLANKS      ON
  15.  
  16.             PRINT       OFF
  17.             INCLUDE        'SysEqu.a'
  18.             INCLUDE        'SysErr.a'
  19.             INCLUDE        'Traps.a'
  20.  
  21.             PRINT       ON
  22.             
  23.             CASE        OBJ
  24.  
  25.  
  26. ASCSIDisk   MAIN        EXPORT     
  27.             
  28.             CASE        OBJECT
  29.             EXPORT        geticon
  30.             EXPORT        A5Setup
  31.             IMPORT        dropen, prime, control, status    ; Disk.c
  32.             IMPORT        drclose,    getRefNum            ; Disk.c
  33.  
  34. Start
  35.             ; Header for the 'Driver Plus'
  36.  
  37.             bra.w    DInst                    ; 4 bytes
  38.             dc.l    1                        ; unused
  39.             bra.w    D2Inst                    ; 4 bytes
  40.             DC.W    $2324                    ; signature
  41.             DC.W    1                        ; ddType
  42.             DC.W    1                        ; version
  43.             DC.W    1                        ; sbDevID
  44.             DC.W    1                        ; sbDevType
  45. drvrsize    DC.L    0                        ; size of driver (in bytes)
  46.     ;
  47.     ;            Note: 'chksum' is the last Header+ field, and must
  48.     ;                start just before the DiskDrvr label
  49.     ;
  50. chksum        DC.L    0                        ; driver checksum (word sum)
  51.  
  52.  
  53. DiskDrvr    ; This is where dCtlDriver in the DCE should be pointing.
  54.  
  55.             ; Regular driver header
  56.  
  57.             DC.W    $6F00                    ; was $4F; uses dNeedTime now
  58.             DC.W    0,0                        ; no delay or EMask
  59.             DC.W    0                        ; no menu
  60.  
  61.             ; Entry point offset table
  62.  
  63.             DC.W    DiskOpen-DiskDrvr        ; open
  64.             DC.W    DiskPrime-DiskDrvr        ; prime
  65.             DC.W    DiskControl-DiskDrvr    ; control
  66.             DC.W    DiskStatus-DiskDrvr        ; status
  67.             DC.W    DiskClose-DiskDrvr        ; close
  68.  
  69. DName        ; Must start after offset table and should occupy 8 bytes.
  70.  
  71.             STRING    ASIS
  72.  
  73.             DC.B    7                        ; name length
  74.             DC.B    '.XMPL00'                ; name to open - last two bytes will
  75.                                             ;  unique value (checksum) inserted.
  76.                                             ;  Or not, we haven't figured out why!
  77.  
  78. ;
  79. ;    WARNING:  Sigoffs must start at an offset of 26 (dec) from
  80. ;                DiskDrvr.  If you change this, the installer program
  81. ;                (routines.c, routines.a) may no longer work for plugging
  82. ;                and unplugging a driver, so be careful!
  83. ;
  84. SigValue    EQU        $41BD30B0                ; arbitrary signature value
  85. SigOffs        DC.L    SigValue                ; offset 26 from DiskDrvr
  86. openmap        DC.W    0                        ; offset 30 from DiskDrvr
  87. mountflag    DC.W    0                        ; offset 32 from DiskDrvr
  88.  
  89. ;_______________________________________________________________________
  90. ;
  91. ; RemoveDrvr
  92. ;
  93. ;    This deallocates the heap space of an identical driver that is
  94. ;    being opened.  After the DisposPtr, the 'older' driver continues
  95. ;    to set up things to handle the new drive.
  96. ;
  97. ; On entry (called by jmp), a0 = 'Start' addr of driver to be
  98. ;    deallocated
  99. ;_______________________________________________________________________
  100.  
  101. RemoveDrvr
  102.             _DisposPtr ,SYS                    ; away with thee!
  103.             bra.w    InstallDCE                ; continue setting up
  104.  
  105.  
  106. ;_______________________________________________________________________
  107. ;
  108. ; A5Setup():
  109. ;
  110. ;    This returns the previous a5 value in D0, and sets A5 to its new value.
  111. ;
  112. ;_______________________________________________________________________
  113.  
  114. A5Setup
  115.             move.l    a5,d0
  116.             move.l    4(sp),a5
  117.             rts
  118.  
  119. ;_______________________________________________________________________
  120. ;
  121. ; Routine:      geticon()
  122. ;
  123. ;    Returns a pointer to the icon.
  124. ;
  125. ;_______________________________________________________________________
  126.  
  127. geticon
  128.             pea        theicon
  129.             move.l    (sp)+,d0
  130.             rts
  131.             
  132. ;_______________________________________________________________________
  133. ;
  134. ; Routine:      DiskOpen
  135. ; Arguments:      A0 (input)  -- pointer to request parameter block
  136. ;                  A1 (input)  -- DCE pointer for driver.
  137. ; Function:     This is just a stub now because _Open is too brain-damaged
  138. ;                to use with multiple drives handled by a single driver.
  139. ;                The real Open code (dropen) is called without involving
  140. ;                the _Open trap at all.
  141. ;_______________________________________________________________________
  142.  
  143. DiskOpen
  144.             moveq.l    #0,d0                    ; say it's OK
  145.             move.w    d0,ioResult(a0)            ; see I.M. II, p. 193
  146.             bra.s    DriverDone2
  147.  
  148. ;_______________________________________________________________________
  149. ;
  150. ; Routine:      DiskClose
  151. ; Arguments:      A0 (input)  -- pointer to request parameter block
  152. ;                  A1 (input)  -- DCE pointer for driver.
  153. ; Function:     If this is the last drive for this driver, remove the
  154. ;                  VBL task, shutdown task, and dispose of driver locals.
  155. ;_______________________________________________________________________
  156.  
  157. DiskClose   
  158.             move.l    a5,-(sp)                ; save A5
  159.             move.l    dCtlStorage(a1),a5        ; setup A5
  160.             move.l    a0,-(sp)                ; param block
  161.             move.l    a1,-(sp)                ; DCE
  162.             jsr        drclose
  163.             bra.s    DriverDone
  164.  
  165. ;_______________________________________________________________________
  166. ;
  167. ; Routine:      DiskControl
  168. ; Arguments:        A0 (input)  -- pointer to control call parameter block
  169. ;                    A1 (input)  -- DCE pointer for driver.
  170. ;                    CSCode:
  171. ;                         1 = KillIO
  172. ;                         5 = Verify
  173. ;                         6 = Format
  174. ;                         7 = Eject
  175. ;                         8 = SetTagBuffer (for 12-byte field only)
  176. ;                        17 = PhysIo (read/write physical, not logical, blocks)
  177. ;                        20 = Icon return (RSRC ID)
  178. ;                        21 = pointer to icon and string
  179. ;
  180. ;_______________________________________________________________________
  181.  
  182. DiskControl
  183.             move.l    a5,-(sp)                ; save A5
  184.             move.l    dCtlStorage(a1),a5        ; setup A5
  185.             move.l    a0,-(sp)                ; param block
  186.             move.l    a1,-(sp)                ; DCE
  187.             jsr        control
  188.             bra.s    DriverDone
  189.  
  190. ;_______________________________________________________________________
  191. ;
  192. ; Routine:      DiskStatus
  193. ; Arguments:      A0 (input)  -- pointer to status call parameter block:
  194. ;
  195. ;                CSCode:
  196. ;                     8 = DrvSts (get drive status)
  197. ;_______________________________________________________________________
  198.  
  199. DiskStatus
  200.             move.l    a5,-(sp)                ; save A5
  201.             move.l    dCtlStorage(a1),a5        ; setup A5
  202.             move.l    a0,-(sp)                ; param block
  203.             move.l    a1,-(sp)                ; DCE
  204.             jsr        status
  205.             bra.s    DriverDone
  206.  
  207. ;_______________________________________________________________________
  208. ;
  209. ; Routine:      DiskPrime
  210. ; Arguments:        A0 (input)  -- pointer to request parameter block
  211. ;                    A1 (input)  -- pointer to disk DCE
  212. ; Function:     The prime entry point is used for drive read/write.
  213. ;
  214. ;_______________________________________________________________________
  215.  
  216. DiskPrime
  217.             move.l    a5,-(sp)                ; save A5
  218.             move.l    dCtlStorage(a1),a5        ; setup A5
  219.             move.l    a0,-(sp)                ; param block
  220.             move.l    a1,-(sp)                ; DCE
  221.             jsr        prime
  222.  
  223. DriverDone                                    ; common for all driver calls
  224.             move.l    (sp)+,a1                ; restore DCE pointer
  225.             move.l    (sp)+,a0                ; restore PB pointer
  226.             move.l    (sp)+,a5                ; restore A5
  227. DriverDone2
  228.             cmp.w    #1,d0                    ; Magic "Handled Async" return from DoNewSCSI?
  229.             bne.b    @DriverDone3            ; Nope, handle normally
  230.             moveq    #0,d0                    ; set return to noErr
  231.             bra.b    @return                    ; mosey on outta here (Let completion routing call iodone)
  232. @DriverDone3
  233.             tst.w    d0                        ; set z bit for test <AG>
  234.             beq.s    @NoError                 ; ... don't update error field unless there is an error <AG>
  235.             move.w    d0,DskErr                ; save last error for file system
  236. @NoError     
  237.             btst    #noQueueBit,ioTrap(a0)    ; immediate call?
  238.             bne.s    @Return                    ; if so, just do an rts
  239.             move.l    JIODone,-(sp)            ; else jump to JIODone
  240. @Return
  241.             rts
  242.  
  243.             
  244.  
  245. ;----------------------------------------------
  246. ;
  247. ;    The icon is currently hard-coded.  It would be nice to make it
  248. ;    more dynamic.
  249. ;
  250.  
  251. theicon            ; 256 bytes long
  252.  
  253.     dc.w        $0000, $8000, $0001, $C000, $0003, $E000, $0867, $F000
  254.     dc.w        $14AF, $7800, $173E, $3C00, $107C, $1E00, $2478, $0F02
  255.     dc.w        $4070, $0786, $8020, $03CA, $0018, $01F2, $0007, $FFE2
  256.     dc.w        $FC00, $FF84, $1E00, $7F84, $3E00, $1F0E, $7980, $000F
  257.     dc.w        $F1C0, $000E, $79C0, $000C, $3DC0, $0008, $1F80, $0004
  258.     dc.w        $0F0F, $FE04, $0710, $0104, $0310, $0384, $0118, $0F44
  259.     dc.w        $011C, $1E44, $011E, $3C44, $022F, $7884, $0447, $F108
  260.     dc.w        $0383, $E0F0, $0001, $C000, $0000, $8000, $0000, $0000
  261.  
  262.     dc.w        $0000, $8000, $0001, $C000, $0003, $E000, $0867, $F000
  263.     dc.w        $1CEF, $F800, $1FFF, $FC00, $1FFF, $FE00, $3FFF, $FF02
  264.     dc.w        $7FFF, $FF86, $FFFF, $FFCE, $FFFF, $FFFE, $FFFF, $FFFE
  265.     dc.w        $FFFF, $FFFC, $1FFF, $FFFC, $3FFF, $FFFE, $7FFF, $FFFF
  266.     dc.w        $FFFF, $FFFE, $7FFF, $FFFC, $3FFF, $FFF8, $1FFF, $FFFC
  267.     dc.w        $0FFF, $FFFC, $07FF, $FFFC, $03FF, $FFFC, $01FF, $FF7C
  268.     dc.w        $01FF, $FE7C, $01FF, $FC7C, $03EF, $F8FC, $07C7, $F1F8
  269.     dc.w        $0383, $E0F0, $0001, $C000, $0000, $8000, $0000, $0000
  270.     ; Drive location string (with length byte)
  271.     ds.b        32
  272.  
  273.     align
  274.  
  275.  
  276.  
  277. ;--------------------------------------------------------------
  278. ;
  279. ;   The SCSI driver loader will get to here.
  280. ;   a0 -> the partition table. d7 = default data start area (in case partition map is bad)
  281. ;   d5 = SCSI ID or Device Ident of device this driver came from.
  282. ;    Need to: Get DCE, point DCE at driver, open driver, fill in
  283. ;    driver locals based on passed environment.
  284. ;
  285.  
  286.  
  287. D2Inst
  288.             bset.l    #29,d5                    ; use this bit as a "Driver43" flag
  289.             bra.b    DrvrInst                ; have at it
  290.  
  291. DInst
  292.             bclr    #29,d5                    ; NOT a "Driver43"
  293. DrvrInst            
  294.             movem.l a2-a6/d2-d7,-(sp)
  295.             
  296.             ; Since the ROM allocates space in the system heap for the
  297.             ; driver in a multiple of a disk block size, we can
  298.             ; return the unused heap space since we know the exact
  299.             ; size in bytes.
  300.             ;
  301.             move.l  a0,a4                    ; save the partition table pointer
  302.             lea        Start,a0                ; start of driver
  303.             move.l    drvrsize,d0                ; # of bytes in driver
  304.             _SetPtrSize                        ; cut back to actual size
  305.  
  306.             moveq    #0,d0                    ; Clear out d0
  307.             moveq    #0,d1                    ; Clear out d1
  308.             move.w    UnitNtryCnt,d0            ; check all DCEs SCSI and above
  309.             sub.l    #32,d0                    ; don't look below that
  310.             move.l    UTableBase,a1            ; find unit table
  311.             move.w    UnitNtryCnt,d1            ; The number of DCEs
  312.             lsl.l    #2,d1                    ; Multiply by the size of an entry
  313.             add.w    d1,a1                    ; point to the end of the table
  314. @0
  315.             move.l    -(a1),d2                ; check next lower DCE
  316.             beq.s    @1                        ; if empty hndl, try again
  317.             move.l    d2,a2                    ; get handle to SCSI DCE
  318.             move.l    (a2),a0                    ; get ptr to DCE
  319.             move.l    (a0),a2                    ; get address of driver
  320.             cmpi.l    #SigValue,Sigoffs-DiskDrvr(a2)    ; same signature?
  321.             bne.s    @1                        ; if not, keep looking
  322.             cmp.l    chksum-DiskDrvr(a2),d3    ; same checksum?
  323.             bne.s    @1                        ; if not, keep looking
  324.             ;
  325.             ; Now we've found a driver which can handle multiple
  326.             ; drives, so we'll jump to it.  There the code does a
  327.             ; DisposPtr on this duplicate driver code, and then goes
  328.             ; on to the InstallDCE code.
  329.             ;
  330.             lea        Start,a0                ; set up for the DisposPtr
  331.             jmp        RemoveDrvr-DiskDrvr(a2)    ; go to his RemoveDrvr...
  332. @1
  333.             dbra    d0,@0                    ; try next slot in table
  334.  
  335.             ;
  336.             ; Bit 31 of d5 is 0 if we were booted by the ROM (in
  337.             ; which case we want to bump up the system heap size),
  338.             ; else it's set by the Installer (leave heap alone).
  339.             ;
  340.             tst.l    d5                        ; if Installer called us...
  341.             bmi.s    InstallDCE                ;   don't do anything else
  342.             
  343.             btst    #$29,d5                    ; New API?
  344.             bne.b    InstallDCE                ; Yep, don't do SetAppBase
  345.  
  346.             move.l    SysZone,a0                ; get start of system heap
  347.             move.l    (a0),a0                    ; get bkLim
  348.             add.w    #$3000,a0                ; add 12K
  349.             move.l    TheZone,-(sp)            ; save so it doesn't get trashed
  350.             _SetAppBase                        ; (boot blocks can make a larger
  351.                                             ;     system heap if they want to)
  352.             move.l    (sp)+,TheZone            ; fixes startup screen bug
  353.  
  354. InstallDCE
  355.             ; First we decide if we are running in a SCSI Manager 4.3 Environment
  356.             ; If so we get a drefnum from the getRefNum function
  357.             ; otherwise we get one the old fashioned way - ie use the assigned one.
  358.  
  359.             movem.l a0-a2/d1-d2,-(sp)
  360.             move.l    d5,-(sp)                ; push the SCSI ID/Device Ident
  361.             jsr        getRefNum                ; Look for New SCSI Manager and get RefNum
  362.             addq.l    #4,sp                    ; pop parameters
  363.             movem.l (sp)+,a0-a2/d1-d2        ; restore regs
  364.             move.w    d0,d4                    ; save a copy of dRefNum
  365.             beq.s    InitExit                ; valid dRefNum? no->skip install
  366.             not.w    d4                        ; turn it into a unit number
  367.             _DrvrInstall                    ; do the DCE shuffle
  368.  
  369.             asl.w    #2,d4                    ; * 4
  370.             move.l    UTableBase,a1            ; point at unit table
  371.             move.l    0(a1,d4.w),a0            ; get the DCE Entry
  372.             move.l    (a0),a6                    ; get the pointer
  373.             _HLock                            ; lock the DCE
  374.  
  375.             lea        DiskDrvr,a0                ; point to the real stuff
  376.             move.l    a0,dCtlDriver(a6)        ; install driver pointer
  377.             move    (a0)+,dCtlFlags(a6)        ; driver flags -> DCE
  378.             move.l    (a0)+,dCtlDelay(a6)        ; copy delay, emask
  379.             move    (a0)+,dCtlMenu(a6)        ; and menu
  380.             bset    #dOpened,dCtlFlags+1(a6)    ; mark the driver open
  381.             bclr    #dRamBased,dCtlFlags+1(a6)    ; mark as ROM based (because DCE contains ptr)
  382.  
  383.             moveq.l    #1,d0                    ; assume we'll mount it
  384.             btst.l    #30,d5                    ; bit 30 used as don't-mount flag
  385.             beq.s    @doopen                    ; not set, so mount as normal
  386.             moveq.l    #0,d0                    ; bit set, so don't mount
  387. @doopen
  388.             move.l    d5,-(sp)                ; Device Ident/SCSI ID
  389.             move.l    d0,-(sp)                ; mountflag
  390.             move.l    a6,-(sp)                ; DCE pointer
  391.             jsr        dropen                    ; return value in d0
  392.             add.l    #12,sp                    ; drop parameters
  393.             tst.w    d0
  394.             beq.s    InitExit                ; branch if OK from open
  395.             move.l    #openErr,d0                ; failed...
  396. InitExit
  397.             movem.l    (sp)+,a2-a6/d2-d7
  398.             rts
  399.  
  400.         ENDP
  401.  
  402. ;*
  403. ;* 94.05.06
  404. ;* The asynchronous SCSI Manager calls this routine when a request completes.
  405. ;* It calls, in turn, a C completion routine that is responsible for continued requests
  406. ;* that may be needed to handle error retries. The C routine returns an OSErr or
  407. ;* the magic "1" value that indicates that another request is in-progress.
  408. ;* If a normal (non-magic) value is returned DRVRCOMPIO calls the normal Device
  409. ;* Manager ioDone procedure to complete driver processing for the original
  410. ;* Prime/Control/whatever request.
  411. ;*
  412. DRVRCOMPIO   PROC        EXPORT     
  413.             IMPORT    completeIO, getDCE
  414.             move.l    4(sp),-(sp)                ; setup parameters
  415.             jsr        getDCE                    ; get the DCE from the parameter block
  416.             move.l    d0,a1                    ; remember it for later
  417.             move.l    (sp)+,d1                ; remember parameter block
  418.             move.l    a1,-(sp)                ; save dce
  419.             move.l    d1,-(sp)                ; setup parameters again
  420.             jsr        completeIO                ; execute the c completion routine
  421.             add.l    #4,sp                    ; clean up the stack
  422.             move.l    (sp)+,a1                ; and finally get the dce back (whew - that was too much work)
  423.             cmp.w    #1,d0                    ; magic - we're not done yet?
  424.             bne.b    @done                    ; nope - call IODone
  425.             move.l    (sp)+,d1                ; remember return value
  426.             add.l    #4,sp                    ; clean up stack (Pascal style function)
  427.             move.l    d1,-(sp)                ; restore return value 
  428.             rts                                ; rts back to SCSI Manager
  429. @done
  430.             tst.w    d0                        ; set z bit for test <AG>
  431.             beq.s    @NoError                 ; ... don't update error field unless there is an error <AG>
  432.             move.w    d0,DskErr                ; save last error for file system
  433. @NoError     
  434.             move.l    (sp)+,d1                ; remember return value
  435.             add.l    #4,sp                    ; clean up stack (Pascal style function)
  436.             move.l    d1,-(sp)                ; restore return value 
  437.             movem.l    a2-a6/d2-d7,-(sp)        ; save stuff around IO/Done
  438.             move.l    JIODone,a2                ; IODone...
  439.             jsr        (a2)                    ; jump to JIODone
  440.             movem.l    (sp)+,a2-a6/d2-d7        ; restore regs
  441.             rts
  442.         ENDP
  443.         END
  444.